package com.system.boot.login.controller;

import cn.hutool.core.util.IdUtil;
import com.system.boot.login.service.ApplyService;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.yang.common.core.constant.SystemConstant;
import org.yang.common.core.exception.BaseException;
import org.yang.common.core.model.ApplyToken;
import org.yang.common.core.model.AuthDto;
import org.yang.common.core.result.BaseController;
import org.yang.common.core.result.R;
import org.yang.common.i18n.enums.RI18nEnum;
import org.yang.common.utils.EncryptUtil;
import org.yang.common.utils.cookie.CookieUtil;
import org.yang.database.cache.utils.RedisUtils;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 登录
 * @author: lslands
 * @description:
 * @version：v1.0
 * @date: 2024/6/6 15:59
 */

@Slf4j
@RestController
@RequiredArgsConstructor
public class LoginController extends BaseController {

    private final ApplyService applyService;
    private final RedisUtils redisUtils;
    private final static String COOKIE_NAME = "UID";
    private final static String DOMAIN="localhost";

    /**
     * 登录
     * @param dto 请求参数
     * @return R<?>
     * @throws BaseException 登录异常
     */
    @PostMapping("/login")
    public R<ApplyToken> login(@RequestBody AuthDto dto) throws BaseException {
        //解密前端加密
        String password = EncryptUtil.aesDecryptForFront(dto.getPassword(),SystemConstant.KEY_DES);
        if(StringUtils.isBlank(password)){
            return R.fail("密码错误");
        }
        String clientSecret = EncryptUtil.aesDecryptForFront(dto.getClientSecret(),SystemConstant.KEY_DES);
        if(StringUtils.isBlank(clientSecret)){
            return R.fail("无效客户端");
        }
        dto.setPassword(password);
        dto.setClientSecret(clientSecret);
        ApplyToken applyToken = applyService.applyToken(dto);
        if(Objects.isNull(applyToken)){
            return R.fail("密码错误");
        }
        String jtl = IdUtil.randomUUID();
        String key=SystemConstant.TOKEN_PREFIX+ jtl;
        //储存获取令牌标识到cookie
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
        if (response != null) {
            CookieUtil.set(response,DOMAIN,"/",COOKIE_NAME,jtl,
                    (int)applyToken.getExpiresIn(),false);
        }
        //储存token到redis中的key
        redisUtils.setCacheObject(key, applyToken,applyToken.getExpiresIn(), TimeUnit.SECONDS);
        return R.success(RI18nEnum.LOGIN_SUCCESS,applyToken);
    }


    /**
     * 获取令牌
     * @return 令牌
     */
    @GetMapping("/getAccessToken")
    public R<ApplyToken> getAccessToken(){
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        Cookie cookie = CookieUtil.get(request, COOKIE_NAME);
        String cookieValue = cookie.getValue();
        if (StringUtils.isBlank(cookieValue)){
            return R.fail("令牌过期");
        }
        //拿身份令牌从redis种查询jwt令牌
        String key = SystemConstant.TOKEN_PREFIX + cookieValue;
        ApplyToken applyToken = redisUtils.getCacheObject(key);
        if(Objects.isNull(applyToken)){
            HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
            if (response != null) {
                CookieUtil.set(response,DOMAIN,"/",COOKIE_NAME,null, 0,false);
            }
            return R.fail("令牌过期");
        }
        return R.success(applyToken);
    }
}
